# -*- coding: utf-8 -*-
"""
    Created by huangyi at 2020/9/1.
    Copyright (c) 2013-present, Xiamen Dianchu Technology Co.,Ltd.
    Description:
    Changelog: all notable changes to this file will be documented
"""
from app.bean.bean_Instantiate_proxy import BeanInstantiateProxy
from app.bean.bean_definition import BeanDefinition, BeanScope
from app.bean.bean_factory import BeanFactory
from app.errors.duplicate_bean import DuplicateBeanException
from app.errors.type_incorrect import TypeIncorrectException
from app.utils.bean_utils import BeanUtils


class NormalBeanFactory(BeanFactory):

    def __init__(self):
        self.name_bean_dict = {}

    def get_bean(self, *args, **kwargs):
        """
        :param args:
        args[0]传str类型，则根据名称获取，传类，则根据类获取
        :param kwargs:
        :return:
        """
        bean = None
        if isinstance(args[0], str):
            bean = self.get_bean_by_name(args[0])
        elif isinstance(args[0], type(object)):
            bean = self.get_bean_by_type(args[0])
        return bean

    def get_bean_by_name(self, name):
        proxy = self.name_bean_dict.get(name)
        return proxy.get_bean()

    def get_bean_by_type(self, type0):
        bean = BeanDefinition(type0)
        proxy = self.name_bean_dict.get(bean.get_class_name())
        return proxy.get_bean()

    def add_bean_by_interface(self, interface, bean_class, scope=BeanScope.Singleton):
        if not isinstance(interface, type(object)):
            raise TypeIncorrectException(f"var interface is not a class {interface}")
        interface_name = BeanUtils.get_full_class_name(interface)
        bean = BeanDefinition(bean_class)
        bean.scope = scope
        if interface_name in self.name_bean_dict:
            raise DuplicateBeanException(f"duplicate bean: {interface_name}")
        self.name_bean_dict[interface_name] = self.__instantiate_bean(bean)

    def add_bean_by_type(self, bean_class, scope=BeanScope.Singleton):
        bean = BeanDefinition(bean_class)
        bean.scope = scope
        bean_instance = self.__instantiate_bean(bean)
        # 获取当前类名称
        type_name = bean.get_class_name()
        if type_name in self.name_bean_dict:
            raise DuplicateBeanException(f"duplicate bean: {type_name}")
        self.name_bean_dict[type_name] = bean_instance

    def add_bean_by_name(self, name, bean_class, scope=BeanScope.Singleton):
        if name in self.name_bean_dict:
            raise DuplicateBeanException(f"duplicate bean: {name}")
        bean = BeanDefinition(bean_class)
        bean.scope = scope
        self.name_bean_dict[name] = self.__instantiate_bean(bean)

    def __instantiate_bean(self, bean_definition):
        return BeanInstantiateProxy(bean_definition)

